package org.sjm.samples.util;

import java.util.Arrays;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.AfterReturning;
import org.aspectj.lang.annotation.AfterThrowing;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;


@Component
@Aspect
public class LogAspect {

	private static Log logger = LogFactory.getLog(LogAspect.class);  
	
	@Pointcut("execution(* org.sjm.samples.web.*.*(..))")
	public void allMethod(){
		
	}
	
	@After("allMethod()")
	public void afterLog(JoinPoint point){
		System.out.println("afterLog ----------- 最终通知");
		System.out.println("afterLog ----------- 目标方法为: " + point.getSignature().getDeclaringTypeName() + "." + point.getSignature().getName());
		System.out.println("afterLog ----------- 参数为:" + Arrays.toString(point.getArgs()));
		System.out.println("afterLog ----------- 被织入的目标对象为:" + point.getTarget());
	}
	
	@AfterReturning(value = "allMethod()", returning = "returnValue")
	public void afterReturningLog(JoinPoint point, Object returnValue){
		System.out.println("afterReturningLog ----------- 返回值后通知");
		System.out.println("afterReturningLog ----------- 目标方法为: " +
				point.getSignature().getDeclaringTypeName() +
				" " + point.getSignature().getName());
		System.out.println("afterReturningLog ----------- 参数为: " +
				Arrays.toString(point.getArgs()));
		System.out.println("afterReturningLog ----------- 返回值: " + returnValue);
	}
	
	@AfterThrowing(throwing = "ex", value = "allMethod()")
	public void afterThrowingLog(Throwable ex){
		System.out.println("afterThrowingLog ----------- 进入异常通知");
		System.out.println("afterThrowingLog ----------- 异常信息: " + ex.getMessage());
	}
	
	@Around("allMethod()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable{
		System.out.println("AROUND ----------- 进入环绕通知");
		long startTime = System.currentTimeMillis();  
		Object obj = pjp.proceed();
		long endTime = System.currentTimeMillis();  
        MethodSignature signature = (MethodSignature) pjp.getSignature();  
        String methodName = signature.getDeclaringTypeName() + "." + signature.getName();  
  
        // 打印耗时的信息  
        this.printExecTime(methodName, startTime, endTime);  
		System.out.println("AROUND ----------- 结束方法调用");
		return obj;
	}
	
	private void printExecTime(String methodName, long startTime, long endTime) {  
        long diffTime = endTime - startTime;  
        logger.warn("-----" + methodName + " 方法执行耗时：" + diffTime + " ms");  
        System.out.println("AROUND ----------- " + methodName + " 方法执行耗时：" + diffTime + " ms");
	} 
}
